package com.me.myFramework.myAop.aop400.intercept.method;

import javax.annotation.Nonnull;
import java.lang.reflect.Method;
import java.util.List;

/**
 * 自己实现 AOP-4：  <p></p>
 *
 * AOP联盟：该接口是执行方法增强的切面执行器，封装了如下公共逻辑：
 * 切面还没有执行完的话，就继续执行下一个切面，否则调用目标方法
 *
 * @author ME
 * @date 2021/9/26
 */
public class ReflectiveMethodInvocation implements MethodInvocation {

    /** 代理类 */
    private Object proxy;
    /** 目标类 */
    private Object target;
    /** 要执行的目标方法 */
    private Method method;
    /** 目标方法的入参 */
    private Object[] args;

    /**
     * 负责执行增强的拦截器，也就是前置增强、后置增强的模板方法
     */
    private List<MethodInterceptor> interceptors;

    /**
     * 拦截器的下标，用来指示即将执行的拦截器。初始值为 -1
     */
    private int currentInterceptorIndex = -1;

    public ReflectiveMethodInvocation(Object proxy, Object target, Method method, Object[] args, @Nonnull List<MethodInterceptor> interceptors) {
        this.proxy = proxy;
        this.target = target;
        this.method = method;
        this.args = args;
        this.interceptors = interceptors;
    }

    /**
     * 切面类的执行器，由执行器决定执行 源方法（目标对象的方法）还是 advice（增强方法）
     *
     * @return 返回值
     * @throws Throwable Throwable
     */
    @Override
    public Object proceed() throws Throwable {
        // 如果当前要执行的拦截器的下标小于 拦截器链的 size，说明还没执行完，通过切面执行器执行 advice（增强方法）
        if (currentInterceptorIndex < this.interceptors.size() - 1) {
            MethodInterceptor interceptor = this.interceptors.get(++currentInterceptorIndex);
            return interceptor.invoke(this);
        }
        else {
            // 如果要执行的拦截器的下标不小于 size，说明执行完了，就执行责任链的终止操作（调用 原始方法）并返回
            return this.method.invoke(this.target, this.args);
        }
    }

    @Override
    public Object getThis() {
        return this.target;
    }

    @Override
    public Method getMethod() {
        return this.method;
    }

    @Override
    public Object[] getArguments() {
        return this.args;
    }
}
